#ifndef INC_MPSC_H
#define INC_MPSC_H

#include "spinlock.h"

#define MPSC_NODE_AS(ptr, type) \
    ((type) (ptr))

#define MPSC_EMPTY 1

typedef struct mpsc_node {
    struct mpsc_node *next;
} mpsc_node_t;

typedef struct {
    struct spinlock lock;
    volatile mpsc_node_t *head;
    volatile mpsc_node_t *tail;
    volatile int locked;
} mpsc_queue_t;

void init_mpsc_node(mpsc_node_t *node);
void init_mpsc_queue(mpsc_queue_t *queue);

int mpsc_push(mpsc_queue_t *queue, mpsc_node_t *node);

void mpsc_pop_acquire(mpsc_queue_t *queue);
mpsc_node_t *mpsc_raw_pop(mpsc_queue_t *queue);
void mpsc_pop_release(mpsc_queue_t *queue);
mpsc_node_t *mpsc_pop(mpsc_queue_t *queue);

#endif